﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;



namespace httpd_client
{

    public partial class Form_Main : Form
    {
        Socket client;

        private void bg_work()
        {
            while (true)
            {
                bg_work_outqueue();
                bg_work_inqueue();
            }
        }

        /// <summary>
        /// 把内部通讯转化为socket通讯
        /// </summary>
        /// <param name="item">
        /// </param>
        /// <returns>
        /// </returns>
        private byte[] bg_message_encode(thrd_comm_entry_t item)
        {
            byte[] msg = new byte[2048];
            int n = 0;
            int i;

            // 长度
            msg[n++] = (byte)((item.data_size + 7) >> 24);
            msg[n++] = (byte)((item.data_size + 7) >> 16);
            msg[n++] = (byte)((item.data_size + 7) >> 8);
            msg[n++] = (byte)((item.data_size + 7) >> 0);
            // 类型
            msg[n++] = (byte)(item.type >> 8);
            msg[n++] = (byte)(item.type >> 0);
            // 方向
            msg[n++] = (byte)item.dir;
            // 序列号
            msg[n++] = (byte)(item.seqno >> 24);
            msg[n++] = (byte)(item.seqno >> 16);
            msg[n++] = (byte)(item.seqno >> 8);
            msg[n++] = (byte)(item.seqno >> 0);
            // 数据
            for (i = 0; i < item.data_size; i++)
            {
                msg[n+i] = item.data_buf[i];
            }
            n += (int)item.data_size;
            // 结束符
            msg[n++] = Encoding.ASCII.GetBytes("\r")[0];
            msg[n++] = Encoding.ASCII.GetBytes("\n")[0];
            msg[n++] = Encoding.ASCII.GetBytes("\r")[0];
            msg[n++] = Encoding.ASCII.GetBytes("\n")[0];

            return msg;
        }

        /// <summary>
        /// 将socket转化为内部通讯
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static thrd_comm_entry_t bg_message_decode(byte[] msg)
        {
            thrd_comm_entry_t item = new thrd_comm_entry_t();
            int i;

            item.data_size = (UInt32)((msg[0] << 24 | msg[1] << 16 | msg[2] << 8 | msg[3]) - 7);
            item.type = (UInt32)(msg[4] << 16 | msg[5]);
            item.dir = msg[6];
            item.seqno = (UInt32)(msg[7] << 24 | msg[8] << 16 | msg[9] << 8 | msg[10]);
            for (i = 0; i < item.data_size; i++)
            {
                item.data_buf[i] = msg[i + 11];
            }

            return item;
        }

        private void bg_send(byte[] data, int len)
        {
            if (client != null)
            {
                AsynchronousClient.Send(client, data, len);
                //log_add_thread("向" + remote + "发送数据：" + data);
            }

        }

        /**
         * 输入队列
         */
        private void bg_work_inqueue()
        {
            thrd_comm_entry_t item;
            thrd_comm_entry_t status = new thrd_comm_entry_t();

            while (tcp_inlist.Count != 0)
            {
                /*
                 * TCP输入队列
                 */
                tcp_in_mutex.WaitOne();
                /*输入队列不为空*/
                item = null;
                if (tcp_inlist.Count > 0)
                {
                    item = tcp_inlist.Dequeue();
                }
                tcp_in_mutex.ReleaseMutex();
                if (item == null)
                {
                    break;
                }
                else
                {
                    switch (item.type)
                    {
                        case sock_type_t.SOCK_TYP_LOG_ENTRY:
                            if (item.dir == task_dir_t.DIR_NO_RESPONSE)
                            {
                                item.type = task_type_t.TYP_LOG;
                                status_mutex.WaitOne();
                                status_inlist.Enqueue(item);
                                status_mutex.ReleaseMutex();
                            }
                            break;
                        default:
                            break;

                    }
                }
                item = null;
            }
        }


        /**
         * 输出队列
         */
        private void bg_work_outqueue()
        {
            thrd_comm_entry_t item = null;
            thrd_comm_entry_t status = new thrd_comm_entry_t();

            while (tcp_outlist.Count > 0)
            {
                tcp_out_mutex.WaitOne();
                if (tcp_outlist.Count > 0)
                {
                    item = null;
                    item = tcp_outlist.Dequeue();
                }
                tcp_out_mutex.ReleaseMutex();

                if (item == null)
                {
                    break;
                }
                else
                {
                    switch (item.type)
                    {
                        case task_type_t.TYP_LOG_SEND_TO_REMOTE:
                            if (item.dir == task_dir_t.DIR_NO_RESPONSE ||
                                item.dir == task_dir_t.DIR_REQUEST)
                            {
                                item.type = (sock_type_t.SOCK_TYP_LOG_GET);//转换为对外通讯的类型
                                bg_send(bg_message_encode(item), (int)item.data_size + 15);
                            }
                            break;
                        case task_type_t.TYP_SERV_QUIT:
                            if (item.dir == task_dir_t.DIR_NO_RESPONSE ||
                                item.dir == task_dir_t.DIR_REQUEST)
                            {
                                item.type = sock_type_t.SOCK_TYP_SERV_QUIT;
                                bg_send(bg_message_encode(item), (int)item.data_size + 15);
                            }
                            break;
                        case task_type_t.TYP_CONNECT_TO_SERV:
                            if (item.dir == task_dir_t.DIR_NO_RESPONSE ||
                                item.dir == task_dir_t.DIR_REQUEST)
                            {
                                String server;
                                int port;
                                int pos;
                                StringBuilder sb = new StringBuilder();
                                server = Encoding.UTF8.GetString(item.data_buf, 0, (int)item.data_size);
                                sb.Append(server);
                                pos = sb.ToString().Trim().IndexOf(":");
                                server = sb.ToString().Trim().Remove(pos);
                                port = Convert.ToInt32(sb.ToString().Trim().Substring(pos + 1), 10);
                                client = AsynchronousClient.StartClient(server, port);
                            }
                            break;
                        case task_type_t.TYP_DISCONNECT_TO_SERV:
                            AsynchronousClient.close(client);
                            item.dir = task_dir_t.DIR_RESPONSE;
                            status_mutex.WaitOne();
                            status_inlist.Enqueue(item);
                            status_mutex.ReleaseMutex();
                            break;
                        default:
                            break;
                    }
                }
                item = null;
            }
        }

        /**/
        void log_add_thread(String log)
        {
            status_mutex.WaitOne();
            thrd_comm_entry_t item = new thrd_comm_entry_t();
            item.data_buf = Encoding.UTF8.GetBytes(log);
            item.data_size = (UInt32)item.data_buf.Length;
            item.dir = task_dir_t.DIR_NO_RESPONSE;
            item.src = 0;
            item.dst = 0;
            item.seqno = 0;
            item.ttl = 128;
            item.session = 0;
            item.type = task_type_t.TYP_LOG;
            status_inlist.Enqueue(item);
            status_mutex.ReleaseMutex();
        }
    }
}